package spu

import (
	"context"
	"fmt"
	"mall/common/excption"
	"mall/common/global"
	constans "mall/services/product/rpc/consts"
	"mall/services/product/rpc/internal/domain/bo"
	"mall/services/product/rpc/internal/mapper"
	"mall/services/product/rpc/internal/mapper/entity"
	"mall/services/product/rpc/internal/svc"
	"mall/services/product/rpc/pb"
	"strings"

	"github.com/zeromicro/go-zero/core/logx"
)

type InsertSpuAttrLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewInsertSpuAttrLogic(ctx context.Context, svcCtx *svc.ServiceContext) *InsertSpuAttrLogic {
	return &InsertSpuAttrLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *InsertSpuAttrLogic) InsertSpuAttr(in *pb.InsertSpuAttrDTO) (*pb.InsertSpuAttrVO, error) {
	// 1.check request
	checkRequestErr, valueMapper := l.checkRequestDTO(in)
	if checkRequestErr != nil {
		return nil, checkRequestErr
	}
	// 2.insert db
	spuAttrValueIdArr, saveErr := l.saveDB(in, valueMapper)
	if saveErr != nil {
		return nil, saveErr
	}
	// 3.return obj
	return &pb.InsertSpuAttrVO{SpuId: in.SpuId, SpuAttrValueId: spuAttrValueIdArr}, nil
}

func (l *InsertSpuAttrLogic) saveDB(in *pb.InsertSpuAttrDTO, valueMapper *mapper.SpuAttrValueMapper) ([]int64, error) {
	var valueEntityArr []entity.SpuAttrValueEntity
	for _, v := range in.SpuAttrValueArr {
		valueEntity := entity.SpuAttrValueEntity{}
		valueEntity.SpuId = in.SpuId
		valueEntity.AttrId = v.AttrValueId
		valueEntity.AttrValueName = v.AttrValueName
		valueEntity.AttrName = v.AttrName
		valueEntity.AttrValueId = v.AttrValueId
		valueEntityArr = append(valueEntityArr, valueEntity)
	}
	spuAttrValueIdArr, err := valueMapper.BatchInsert(l.ctx, l.svcCtx.DBEngin, valueEntityArr)
	if err != nil {
		return nil, err
	}
	return spuAttrValueIdArr, nil
}

func (l *InsertSpuAttrLogic) checkRequestDTO(in *pb.InsertSpuAttrDTO) (error, *mapper.SpuAttrValueMapper) {
	spuMapper := mapper.NewSpuMapper[entity.SpuEntity]()
	selectCountCtx, err := spuMapper.SelectCountCtx(l.ctx, l.svcCtx.DBEngin, bo.SpuBO{
		SpuId: in.SpuId,
	})
	if err != nil {
		return err, nil
	}
	if selectCountCtx <= 0 {
		return excption.NewErrCode(constans.SpuInfoNoExistError), nil
	}
	spuAttrValueArr := in.GetSpuAttrValueArr()
	var attrValueIdArr []int64
	for _, v := range spuAttrValueArr {
		attrValueIdArr = append(attrValueIdArr, v.AttrValueId)
	}
	valueMapper := mapper.NewSpuAttrValueMapper()
	selectListCtx, err := valueMapper.SelectListCtx(l.ctx, l.svcCtx.DBEngin, bo.SpuAttrValueBO{SpuId: in.SpuId, AttrValueIdArr: attrValueIdArr})
	if err != nil {
		return err, nil
	}
	if len(selectListCtx) > 0 {
		var attrValueDetail []string
		for _, v := range selectListCtx {
			attrValueDetail = append(attrValueDetail, v.AttrValueName)
		}
		printfErr := fmt.Sprintf(
			global.ErrorMessageMap[constans.SpuAttrValueRepeatError],
			strings.Join(attrValueDetail, ","),
		)
		return excption.NewErrCodeMsg(constans.SpuAttrValueRepeatError, printfErr), nil
	}
	return nil, valueMapper
}
